package me.yuzho.study.concurrency.java8;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class Case4InvokeAll {
    
    public static Callable<String> callable(String result, long sleepSeconds) {
        return () -> {
            TimeUnit.SECONDS.sleep(sleepSeconds);
            return result;
        };
    }
    
    public static void main(String[] args) throws InterruptedException, ExecutionException {
       
        // Create an executor
        /*
         * newWorkStealingPool: This factory method is part of Java 8 
         * and returns an executor of type ForkJoinPool 
         * which works slightly different than normal executors.
         * Instead of using a fixed size thread-pool 
         * ForkJoinPools are created for a given parallelism size 
         * which per default is the number of available cores of the hosts CPU.
         */
        ExecutorService executor = Executors.newWorkStealingPool();

        // Create a list of callable tasks
        List<Callable<String>> callables = Arrays.asList(
                () -> "task1",
                () -> "task2",
                () -> "task3");

        executor.invokeAll(callables)
            .stream()
            .map(future -> {
                try {
                    return future.get();
                }
                catch (Exception e) {
                    throw new IllegalStateException(e);
                }
            })
            .forEach(System.out::println);
        
        callables = Arrays.asList(
                callable("task1", 2),
                callable("task2", 1),
                callable("task3", 3));

            String result = executor.invokeAny(callables);
            System.out.println(result);
    }

}
